;(function () {
    const ACCESS_UNIQUE_VISITOR_COOKIE_NAME = 'jprocms-access-unique-visitor';
    const ACCESS_SESSION_ID_COOKIE_NAME = 'jprocms-access-session-id';
    const ACCESS_ENTRY_URL_COOKIE_NAME = 'jprocms-access-entry-url';
    const ACCESS_NEW_VISITOR_COOKIE_NAME = 'jprocms-new-visitor';
    const ACCESS_START_COOKIE_NAME = 'jprocms-access-start';
    const ACCESS_DURATION_COOKIE_NAME = 'jprocms-access-duration';
    const ACCESS_OPENS_COOKIE_NAME = 'jprocms-access-opens';
    const ACCESS_HIDDEN_COOKIE_NAME = 'jprocms-access-hidden';

    // 获取独立访客标识
    function getEntryUrl() {
        let entryUrl = Cookies.get(ACCESS_ENTRY_URL_COOKIE_NAME);
        if (!entryUrl) {
            entryUrl = document.location.href;
            Cookies.set(ACCESS_ENTRY_URL_COOKIE_NAME, entryUrl);
        }
        return entryUrl;
    }

    function getNewVisitor() {
        const newVisitor = Cookies.get(ACCESS_NEW_VISITOR_COOKIE_NAME);
        return newVisitor === 'true';
    }

    function setNewVisitor(newVisitor) {
        Cookies.set(ACCESS_NEW_VISITOR_COOKIE_NAME, String(newVisitor));
    }

    // 获取独立访客标识
    function getUniqueVisitor() {
        let uv = Cookies.get(ACCESS_UNIQUE_VISITOR_COOKIE_NAME);
        if (!uv) {
            uv = String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
            Cookies.set(ACCESS_UNIQUE_VISITOR_COOKIE_NAME, uv, {expires: 3650});
            setNewVisitor(true);
        }
        return uv;
    }

    // 获取会话标识
    function getSessionId() {
        let sessionId = Cookies.get(ACCESS_SESSION_ID_COOKIE_NAME);
        if (!sessionId) {
            sessionId = String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
            Cookies.set(ACCESS_SESSION_ID_COOKIE_NAME, sessionId);
        }
        return sessionId;
    }

    function getStartTime() {
        let startTime = Cookies.get(ACCESS_START_COOKIE_NAME);
        return startTime ? parseInt(startTime) : undefined;
    }

    //设置开始访问时间
    function setStartTime(startTime) {
        if (startTime != null) {
            Cookies.set(ACCESS_START_COOKIE_NAME, String(startTime));
        } else {
            Cookies.remove(ACCESS_START_COOKIE_NAME);
        }
    }

    function getHiddenTime() {
        let hiddenTime = Cookies.get(ACCESS_HIDDEN_COOKIE_NAME);
        return hiddenTime ? parseInt(hiddenTime) : undefined;
    }

    //设置隐藏时间
    function setHiddenTime(hiddenTime) {
        if (hiddenTime != null) {
            Cookies.set(ACCESS_HIDDEN_COOKIE_NAME, String(hiddenTime));
        } else {
            Cookies.remove(ACCESS_HIDDEN_COOKIE_NAME);
        }
    }

    // 获取访问时长
    function getDuration() {
        let duration = Cookies.get(ACCESS_DURATION_COOKIE_NAME);
        return duration ? parseInt(duration) : 0;
    }

    function setDuration(duration) {
        Cookies.set(ACCESS_DURATION_COOKIE_NAME, String(duration));
    }

    function resetCookie() {
        setNewVisitor(false);
        Cookies.remove(ACCESS_SESSION_ID_COOKIE_NAME);
        Cookies.remove(ACCESS_START_COOKIE_NAME);
        Cookies.remove(ACCESS_DURATION_COOKIE_NAME);
    }

    function reOpen() {
        // 超过4小时没有刷新页面或打开页面，重新计时
        if (getHiddenTime() != null && Date.now() - getHiddenTime() > 4 * 60 * 60 * 1000) {
            resetCookie();
        }
        setHiddenTime(null);
        let reOpens = Cookies.get(ACCESS_OPENS_COOKIE_NAME);
        if (reOpens == null) {
            reOpens = '0';
        }
        let opens = parseInt(reOpens) + 1;
        Cookies.set(ACCESS_OPENS_COOKIE_NAME, String(opens));
        if (opens > 0 && getStartTime() == null) {
            setStartTime(Date.now());
        }
        return opens;
    }

    function pageHide() {
        let reOpens = Cookies.get(ACCESS_OPENS_COOKIE_NAME);
        if (!reOpens) {
            reOpens = '0';
        }
        let opens = parseInt(reOpens) - 1;
        if (opens < 0) {
            opens = 0;
        }
        Cookies.set(ACCESS_OPENS_COOKIE_NAME, String(opens));
        const visitStart = getStartTime();
        if (opens <= 0 && visitStart != null) {
            const duration = Math.floor((Date.now() - parseInt(visitStart)) / 1000);
            // 保存浏览时长，清除开始时间
            setDuration(getDuration() + duration);
            setStartTime(null);
            // 设置隐藏时间
            setHiddenTime(Date.now());
        }
        return opens;
    }

    function getCurrentDuration() {
        const visitStart = getStartTime();
        if (visitStart != null) {
            const duration = Math.floor((Date.now() - parseInt(visitStart)) / 1000);
            return getDuration() + duration;
        }
        return getDuration();
    }

    function getAccessUrl(count) {
        const newVisitor = count >= 1 ? String(getNewVisitor()) : 'false';
        return accessApi + '/flow/' + accessSiteId + '?url=' + encodeURIComponent(document.location.href) +
            decodeURI('&referrer=') + encodeURIComponent(document.referrer) +
            decodeURI('&entryUrl=') + encodeURIComponent(getEntryUrl()) +
            decodeURI('&uv=') + getUniqueVisitor() +
            decodeURI('&sessionId=') + getSessionId() +
            decodeURI('&duration=') + getCurrentDuration() +
            decodeURI('&newVisitor=') + newVisitor +
            decodeURI('&count=') + count;
    }

    function doPostVisitReq(callback) {
        callback();
    }

    // 发送请求
    function sendRequest() {
        doPostVisitReq(function () {
            const xhr = new XMLHttpRequest();
            const formData = new FormData();
            xhr.open('POST', getAccessUrl(1), false);
            xhr.send(formData);
        });
    }

    document.addEventListener('visibilitychange', function () {
        if (document.visibilityState === 'hidden') {
            // 页面变为不可见状态时执行的操作
            pageHide();
            doPostVisitReq(function () {
                const formData = new FormData();
                navigator.sendBeacon(getAccessUrl(0), formData);
            });
        } else if (document.visibilityState === 'visible') {
            // 页面变为可见状态时执行的操作
            reOpen();
        }
    });
    if (document.visibilityState === 'visible') {
        reOpen();
    }
    sendRequest();
}());
